package main

import (
  "bufio"
  "fmt"
  "os"
  "os/exec"
  "strings"
)

func main() {
  // filePath := "D:/code_zch/code_script_bat_sh/git-manage/my-repo-2.txt"
  filePath := "my-repos-path.txt"
  changeLogPath := "./logs/git-status-result-change.log"
  cleanLogPath := "./logs/git-status-result-clean.log"
  errorLogPath := "./logs/git-status-result-error.log"
  checkRepositories(filePath, changeLogPath, cleanLogPath, errorLogPath)
}

func checkRepositories(filePath, changeLogPath, cleanLogPath, errorLogPath string) {
  file, err := os.Open(filePath)
  if err != nil {
    logToFile(errorLogPath, fmt.Sprintf("Error opening the file: %s\n", err))
    return
  }
  defer func(file *os.File) {
    err := file.Close()
    if err != nil {
      logToFile(errorLogPath, fmt.Sprintf("Error closing the file: %s\n", err))
    }
  }(file)

  scanner := bufio.NewScanner(file)
  for scanner.Scan() {
    repoPath := scanner.Text()
    repoPath = strings.TrimSpace(repoPath) // Remove any leading/trailing whitespaces.
    if repoPath == "" {
      continue // Skip empty lines
    }

    status, err := getGitStatus(repoPath)
    if err != nil {
      logToFile(errorLogPath, fmt.Sprintf("Repository: %s Error: %s\n", repoPath, err))
      continue
    }

    if strings.TrimSpace(status) == "" {
      logToFile(cleanLogPath, fmt.Sprintf("Repository: %s Status: No changes.\n", repoPath))
    } else {
      logToFile(changeLogPath, fmt.Sprintf("Repository: %s Status: Changes detected.,use cmd: \n  cd /d %s && git status\n", repoPath, repoPath))
    }
  }

  if err := scanner.Err(); err != nil {
    logToFile(errorLogPath, fmt.Sprintf("Error reading the file: %s\n", err))
  }
}

func getGitStatus(repoPath string) (string, error) {
  cmd := exec.Command("git", "-C", repoPath, "status", "--porcelain")
  output, err := cmd.CombinedOutput()
  if err != nil {
    return "", err
  }
  return string(output), nil
}

func logToFile(filename, message string) {
  f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
  if err != nil {
    fmt.Printf("Error opening log file: %s\n", err)
    // If logging fails, just print to standard output
    return
  }
  defer func(f *os.File) {
    err := f.Close()
    if err != nil {
      logToFile(filename, fmt.Sprintf("Error opening the file: %s\n", err))
    }
  }(f)

  if _, err := f.WriteString(message); err != nil {
    fmt.Printf("Error writing to log file: %s\n", err)
    // If writing to the file fails, just print to standard output
  }
}
